﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using EBA.Dynamic;
using System.Dynamic;

namespace EBA.Tests.Dynamic
{
    [TestClass]
    public class ObjectMethodTest
    {
        [TestMethod]
        public void Test_Mock_Action_With_Zero_Parameter()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();
            mock.TestAction();
            Assert.AreEqual("ParameterlessAction", obj.Ret);
        }

        [TestMethod]
        public void Test_Mock_Action_With_One_Parameter()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();
            mock.TestAction("OnlyOneParameter");
            Assert.AreEqual("OnlyOneParameter", obj.Ret);
        }

        [TestMethod]
        public void Test_Mock_Action_With_Parameters()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();
            mock.TestAction("first", 2);
            Assert.AreEqual("first,2", obj.Ret);
        }


        [TestMethod]
        public void Test_Mock_Function_With_Zero_Parameter()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();

            Assert.AreEqual(obj.TestFunction(), mock.TestFunction());
        }

        [TestMethod]
        public void Test_Mock_Function_With_One_Parameter()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();

            Assert.AreEqual(obj.TestFunction("s"), mock.TestFunction("s"));
        }


        [TestMethod]
        public void Test_Mock_Function_With_Parameters()
        {
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();

            Assert.AreEqual(obj.TestFunction("s", 1), mock.TestFunction("s", 1));
        }

        [TestMethod]
        public void Test_Mock_Function_With_Custom_Parameters_And_Custom_Return()
        {
            var custom = new CustomObject { };
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();

            Assert.ReferenceEquals(custom, mock.TestFunction(custom));
        }

        [TestMethod]
        public void Test_Mock_Function_With_Custom_Parameters_And_Struct_Return()
        {
            var custom = new CustomObject { };
            var obj = new TestObject();

            var mock = obj.DynamicCastTo<ITest>();

            Assert.ReferenceEquals(2, mock.TestFunction(2));

            var time = DateTime.Now;
            Assert.ReferenceEquals(time, mock.TestFunction(time));
        }


        #region Helper
        public class TestObject
        {
            public string Ret { get; set; }

            public void TestAction()
            {
                this.Ret = "ParameterlessAction";
            }

            public void TestAction(string arg)
            {
                this.Ret = arg;
            }

            public void TestAction(string arg1, int arg2)
            {
                this.Ret = string.Format("{0},{1}", arg1, arg2);
            }


            public string TestFunction()
            {
                return "TestFunction";
            }

            public string TestFunction(string s)
            {
                return s;
            }

            public string TestFunction(string arg1, int arg2)
            {
                return string.Format("{0},{1}", arg1, arg2);
            }

            public CustomObject TestFunction(CustomObject obj)
            {
                return obj;
            }

            public int TestFunction(int num)
            {
                return num;
            }

            public DateTime TestFunction(DateTime time)
            {
                return time;
            }
        }

        public class CustomObject
        {

        }

        public interface ITest
        {
            void TestAction();
            void TestAction(string arg1);
            void TestAction(string arg1, int arg2);

            string TestFunction();
            string TestFunction(string s);
            string TestFunction(string arg1, int arg2);

            CustomObject TestFunction(CustomObject obj);

            int TestFunction(int num);

            DateTime TestFunction(DateTime time);
        }
        #endregion
    }
}
